home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 2000
/
MacHack 2000.toast
/
pc
/
The Hacks
/
DockStrip
/
MorePatches
/
MoreCFMPatches
/
MoreCFMPatchesTest
/
MoreCFMPatchesTest.c
next >
Wrap
C/C++ Source or Header
|
2000-06-23
|
8KB
|
288 lines
/*
File: MoreCFMPatches.c
Contains: Test CFM patching technology.
Written by: Quinn
Copyright: Copyright © 1998-1999 by Apple Computer, Inc., all rights reserved.
You may incorporate this Apple sample source code into your program(s) without
restriction. This Apple sample source code has been provided "AS IS" and the
responsibility for its operation is yours. You are not permitted to redistribute
this Apple sample source code as "Apple sample source code" after having made
changes. If you're going to re-distribute the source, we require that you make
it clear in the source that the code was descended from Apple sample source
code, but that you've made changes.
Change History (most recent first):
<1> 16/3/99 Quinn First checked in.
*/
/////////////////////////////////////////////////////////////////
// MoreIsBetter Setup
#include "MoreSetup.h"
// Mac OS Interfaces
#include <CodeFragments.h>
#include <LowMem.h>
// ANSI C Interfaces
#include <stdio.h>
#include <string.h>
// Project Interfaces
#include "MoreCFMPatches.h"
/////////////////////////////////////////////////////////////////
#pragma mark ---- Basic Functionality -----
// In this test, we patch LMGetScrDmpEnb twice, call through
// to the existing routine in both patches, while printing out
// entry and exit markers. Seems to work (-:
typedef pascal UInt8 (*LMGetScrDmpEnbProc)(void);
static pascal UInt8 MyLMGetScrDmpEnb(void)
{
UInt8 result;
printf(" Enter MyLMGetScrDmpEnb\n");
result = ( (LMGetScrDmpEnbProc) gMoreCFMPatchesCallThrough)();
printf(" Leave MyLMGetScrDmpEnb\n");
return result;
}
static pascal UInt8 MyLMGetScrDmpEnb2(void)
{
UInt8 result;
printf(" Enter MyLMGetScrDmpEnb2\n");
result = ( (LMGetScrDmpEnbProc) gMoreCFMPatchesCallThrough)();
printf(" Leave MyLMGetScrDmpEnb2\n");
return result;
}
static void BasicFunctionality(void)
{
OSStatus err;
OSStatus junk;
CFragConnectionID connID;
Ptr junkMain;
Str255 junkMessage;
CFragSymbolClass junkSymClass;
Ptr symAddr;
UInt8 junkUInt8;
void *origCodePointer;
printf("Basic functionality testing...\n");
err = GetSharedLibrary("\pInterfaceLib", kPowerPCCFragArch, kFindCFrag, &connID, &junkMain, junkMessage);
if (err == noErr) {
err = FindSymbol(connID, "\pLMGetScrDmpEnb", &symAddr, &junkSymClass);
}
if (err == noErr) {
origCodePointer = ((TVector *)symAddr)->codePointer;
err = MorePatchTVector((TVector *) symAddr, (TVector *) MyLMGetScrDmpEnb, 'KWN1', nil);
if (err == noErr) {
MoreAssertQ(origCodePointer != ((TVector *)symAddr)->codePointer);
err = MorePatchTVector((TVector *) symAddr, (TVector *) MyLMGetScrDmpEnb2, 'KWN2', nil);
if (err == noErr) {
junkUInt8 = LMGetScrDmpEnb();
junk = MoreUnpatchTVector((TVector *) symAddr, (TVector *) MyLMGetScrDmpEnb2);
MoreAssertQ(junk == noErr);
}
junk = MoreUnpatchTVector((TVector *) symAddr, (TVector *) MyLMGetScrDmpEnb);
MoreAssertQ(junk == noErr);
}
MoreAssertQ(origCodePointer == ((TVector *)symAddr)->codePointer);
}
if (err == noErr) {
printf("Success!\n");
} else {
printf("Failed with error %ld.\n", err);
}
}
/////////////////////////////////////////////////////////////////
#pragma mark ---- Ordering Tests -----
typedef void (*OrderProc)(char *str);
static void OBase(char *str)
{
strcpy(str, "OBase");
}
static void O1(char *str)
{
((OrderProc) gMoreCFMPatchesCallThrough)(str);
strcat(str, "->O1");
}
static void O2(char *str)
{
((OrderProc) gMoreCFMPatchesCallThrough)(str);
strcat(str, "->O2");
}
static void O3(char *str)
{
((OrderProc) gMoreCFMPatchesCallThrough)(str);
strcat(str, "->O3");
}
static void OrderingTests(void)
// Tests that patches are applied in the order we expected
// and that they are executed in the order they're applied.
{
OSStatus junk;
char str[256];
OrderProc obaseProc;
printf("Ordering tests...\n");
// We call OBase through a routine pointer to force it to go through
// the TVector. Otherwise, because the routine is implemented in the
// same file as the caller, the compiler optimises the TVector goop away.
obaseProc = OBase;
obaseProc(str);
MoreAssertQ(strcmp(str, "OBase") == 0);
junk = MorePatchTVector((TVector *) OBase, (TVector *) O1, 'Oone', nil);
MoreAssertQ(junk == noErr);
obaseProc(str);
MoreAssertQ(strcmp(str, "OBase->O1") == 0);
junk = MorePatchTVector((TVector *) OBase, (TVector *) O2, 'Otwo', nil);
MoreAssertQ(junk == noErr);
obaseProc(str);
MoreAssertQ(strcmp(str, "OBase->O1->O2") == 0);
junk = MorePatchTVector((TVector *) OBase, (TVector *) O3, 'Otri', nil);
MoreAssertQ(junk == noErr);
obaseProc(str);
MoreAssertQ(strcmp(str, "OBase->O1->O2->O3") == 0);
// Here we try a difficult case, namely pulling a patch out
// of the middle of the patch chain.
junk = MoreUnpatchTVector((TVector *) OBase, (TVector *) O2);
MoreAssertQ(junk == noErr);
obaseProc(str);
MoreAssertQ(strcmp(str, "OBase->O1->O3") == 0);
junk = MoreUnpatchTVector((TVector *) OBase, (TVector *) O1);
MoreAssertQ(junk == noErr);
obaseProc(str);
MoreAssertQ(strcmp(str, "OBase->O3") == 0);
junk = MoreUnpatchTVector((TVector *) OBase, (TVector *) O3);
MoreAssertQ(junk == noErr);
obaseProc(str);
MoreAssertQ(strcmp(str, "OBase") == 0);
printf("Success!\n");
}
#pragma mark ---- Information Tests -----
static OSStatus PrintPatchChain(TVector *patchedTVector)
{
OSStatus err;
ItemCount patchCount;
ItemCount patchIndex;
OSType creator;
TVector *tVector;
void *refcon;
err = MoreCountPatches(patchedTVector, &patchCount);
if (err == noErr) {
for (patchIndex = 1; patchIndex <= patchCount; patchIndex++) {
err = MoreGetIndexedPatchInfo(patchedTVector, patchIndex, kPatchInfoCreator, &creator, sizeof(creator));
if (err == noErr) {
err = MoreGetIndexedPatchInfo(patchedTVector, patchIndex, kPatchInfoTVector, &tVector, sizeof(tVector));
}
if (err == noErr) {
err = MoreGetIndexedPatchInfo(patchedTVector, patchIndex, kPatchInfoRefcon, &refcon, sizeof(refcon));
}
if (err == noErr) {
printf("%ld $%08lx '%4.4s' $%ld -> ", patchIndex, tVector, &creator, refcon);
} else {
break;
}
}
printf("\n");
}
return err;
}
static void InformationTests(void)
// Tests that the patch information routines are
// working as expected.
{
OSStatus junk;
printf("Information tests...\n");
junk = MorePatchTVector((TVector *) OBase, (TVector *) O1, 'Oone', (void *) 1);
MoreAssertQ(junk == noErr);
junk = PrintPatchChain((TVector *) OBase);
MoreAssertQ(junk == noErr);
junk = MorePatchTVector((TVector *) OBase, (TVector *) O2, 'Otwo', (void *) 2);
MoreAssertQ(junk == noErr);
junk = PrintPatchChain((TVector *) OBase);
MoreAssertQ(junk == noErr);
junk = MorePatchTVector((TVector *) OBase, (TVector *) O3, 'Otri', (void *) 3);
MoreAssertQ(junk == noErr);
junk = PrintPatchChain((TVector *) OBase);
MoreAssertQ(junk == noErr);
junk = MoreUnpatchTVector((TVector *) OBase, (TVector *) O2);
MoreAssertQ(junk == noErr);
junk = PrintPatchChain((TVector *) OBase);
MoreAssertQ(junk == noErr);
junk = MoreUnpatchTVector((TVector *) OBase, (TVector *) O1);
MoreAssertQ(junk == noErr);
junk = PrintPatchChain((TVector *) OBase);
MoreAssertQ(junk == noErr);
junk = MoreUnpatchTVector((TVector *) OBase, (TVector *) O3);
MoreAssertQ(junk == noErr);
junk = PrintPatchChain((TVector *) OBase);
MoreAssertQ(junk == kVectorNotPatchedByUsErr);
printf("Success!\n");
}
/////////////////////////////////////////////////////////////////
#pragma mark ---- Main Line -----
void main(void)
{
printf("Hello Cruel World!\n");
printf("MoreCFMPatchesTest\n");
printf("-- A simple test program for the MoreCFMPatches library.\n");
BasicFunctionality();
printf("\n");
OrderingTests();
printf("\n");
InformationTests();
printf("\n");
printf("Done. Press command-Q to Quit.\n");
}